﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.LightSwitch;
using Microsoft.LightSwitch.Security.Server;
using System.Linq.Expressions;
using Microsoft.AspNet.SignalR;
using Microsoft.LightSwitch.Details;

namespace LightSwitchApplication
{
    public partial class MMC_ContentService
    {
        partial void Cars_Filter(ref Expression<Func<Car, bool>> filter)
        {
            // If you are not an Administrator -- you can see you cars only
            //if (!this.Application.User.HasPermission(Permissions.SecurityAdministration))
            {
                filter = e => e.UserName == this.Application.User.Name;
            }
        }

        partial void Places_Filter(ref Expression<Func<Place, bool>> filter)
        {
            //User should be able to see own and shared places
            //if (!this.Application.User.HasPermission(Permissions.SecurityAdministration))
            {
                filter = e => (e.UserName == this.Application.User.Name || e.IsShared == true);
            }
        }

        partial void Favorites_Filter(ref Expression<Func<Favorite, bool>> filter)
        {
            //User should be able to see own favorites only
            //if (!this.Application.User.HasPermission(Permissions.SecurityAdministration))
            {
                filter = e => (e.Car.UserName == this.Application.User.Name);
            }
        }


        partial void Restrictions_Filter(ref System.Linq.Expressions.Expression<Func<Restriction, bool>> filter)
        {
            //User should be able to see own and shared places restrictions
            //if (!this.Application.User.HasPermission(Permissions.SecurityAdministration))
            /*{
                filter = e => (e.Place.UserName == this.Application.User.Identity.Name || e.Place.IsShared == true);
            }*/
        }


        partial void Movements_Filter(ref Expression<Func<Movement, bool>> filter)
        {
            //User should be able to see own movements only.
            //if (!this.Application.User.HasPermission(Permissions.SecurityAdministration))
            {
                filter = e => (e.Car.UserName == this.Application.User.Name);
            }
        }

        partial void Movements_Validate(Movement entity, EntitySetValidationResultsBuilder results)
        {
            if (entity.Car != null && entity.SwapMovement != null && entity.Car.Id == entity.SwapMovement.Car_Movement)
            {
                //you can't swap the same car
                results.AddEntityError("Swapping cars should not be the same");
            }
            if (entity.SwapMovement != null && entity.Id == entity.SwapMovement.Id)
            {
                //you can't swap the same movement
                results.AddEntityError("Swapping movements should not be the same");
            }
            //if (entity.Hours.HasValue)
            //{
            //    DateTime dt = entity.DateFrom.AddHours((double)entity.Hours);
            //    if (entity.DateTo != dt)
            //    {
            //        entity.DateTo = dt;
            //    }
            //}
            //else
            //{
            /*
            if (entity.DateTo.HasValue)
            {
                entity.Hours = (short)((DateTime)entity.DateTo - (DateTime)entity.DateFrom).Hours;
                entity.Minutes = (short)((DateTime)entity.DateTo - (DateTime)entity.DateFrom).Minutes;
            }
            else
            {
                entity.DateTo = entity.DateFrom;
            }
             */ 
            //}
            
            /*
            if (entity.Place != null && entity.Place.PlacesRestrictions.Count() > 0)
            {
                DayOfWeek dateFrom = entity.DateFrom.DayOfWeek;
                //hours + day of week restriction

                var placeRestrictions = entity.Place.PlacesRestrictions;
                var placeRegulations = placeRestrictions.Where(pr =>pr.Restriction.RestrictionRegulations.Where(rr => ((rr.DateFrom.Value.Hour <= entity.DateFrom.Hour && entity.DateFrom.Hour <= rr.DateTo.Value.Hour)
                                || (rr.DateFrom.Value.Hour <= entity.DateTo.Value.Hour && entity.DateTo.Value.Hour <= rr.DateTo.Value.Hour)
                                || (entity.DateFrom.Hour <= rr.DateFrom.Value.Hour && rr.DateFrom.Value.Hour <= entity.DateTo.Value.Hour)
                                || (entity.DateFrom.Hour <= rr.DateTo.Value.Hour && rr.DateTo.Value.Hour <= entity.DateTo.Value.Hour)
                                )
                            && (
                                (dateFrom == DayOfWeek.Monday && rr.Monday == true)
                                || (dateFrom == DayOfWeek.Monday && rr.Monday == true)
                                || (dateFrom == DayOfWeek.Tuesday && rr.Tuesday == true)
                                || (dateFrom == DayOfWeek.Wednesday && rr.Wednesday == true)
                                || (dateFrom == DayOfWeek.Thursday && rr.Thursday == true)
                                || (dateFrom == DayOfWeek.Friday && rr.Friday == true)
                                || (dateFrom == DayOfWeek.Saturday && rr.Saturday == true)
                                || (dateFrom == DayOfWeek.Sunday && rr.Sunday == true)
                            );
                //if (restriction == null)
                //{
                //    //general restriction has minimal priority
                //    restriction = entity.Place.Restrictions.Where(r => !r.DateFrom.HasValue && !r.DateTo.HasValue
                //            && !r.Moday.HasValue && !r.Tuesday.HasValue && !r.Wednesday.HasValue && !r.Thursday.HasValue && !r.Friday.HasValue && !r.Saturday.HasValue && !r.Sunday.HasValue
                //        ).FirstOrDefault();
                //}

                if (!entity.Amount.HasValue && placeRestriction != null)
                {
                    //parking area does not charge for each hour ???
                    entity.Amount = (placeRestriction.Restriction.Price.HasValue ? placeRestriction.Restriction.Price * (decimal)entity.Hours + placeRestriction.Restriction.Price * (((decimal)entity.Minutes) / 60) : 1) * placeRestriction.Restriction.Price;
                }
                if (placeRestriction != null && placeRestriction.Restriction.Hours.HasValue && placeRestriction.Restriction.Hours * 60 + placeRestriction.Restriction.Minutes < entity.Hours * 60 + entity.Minutes)
                {
                    //parking area has time restriction which is affected
                    results.AddEntityError("Parking area " + entity.Place.Name + " located at " + entity.Place.Address 
                        + " has time restriction " + placeRestriction.Restriction.Hours.ToString() + " which exceeds the movement hours");
                }
            }
             */ 
        }

        partial void Cars_Validate(Car entity, EntitySetValidationResultsBuilder results)
        {
            if (entity.UserName == null)
            {
                entity.UserName = this.Application.User.Identity.Name;
            }
        }

        partial void Places_Validate(Place entity, EntitySetValidationResultsBuilder results)
        {
            if (!string.IsNullOrEmpty(entity.UserName) && entity.UserName != this.Application.User.Identity.Name) 
            {
                results.AddEntityError("The user can't modify place created by other user");
            }
            else if (entity.UserName == null)
            {
                entity.UserName = this.Application.User.Identity.Name;
            }
            if (entity.IsShared == null) 
            {
                entity.IsShared = false;
            }
        }

        partial void Places_Inserted(Place entity)
        {
            string message = string.Format("A place with id:{0}, address:{1}, name:{2} was just created by {3}"
                , entity.Id.ToString(), entity.Address, entity.Name, Application.User.Name);
            var context = GlobalHost.ConnectionManager.GetHubContext<PlaceHub>();
            //context.Clients.All.broadcastMessage(message);
            //context.Clients.OthersInGroup(groupName).addMessage(data);
            var hub = new PlaceHub(entity.Id);
            hub.SendToGroup(entity.Id.ToString(), message);
        }
        
        partial void Places_Updated(Place entity)
        {
            string message = string.Format("A place with id:{0}, address:{1}, name:{2} was just updated by {3}"
                , entity.Id.ToString(), entity.Address, entity.Name, Application.User.Name);

            //var context = GlobalHost.ConnectionManager.GetHubContext<PlaceHub>();
            //context.Clients.All.broadcastMessage(message);
            //context.Clients.Group(entity.Id).addMessage(message);
            var hub = new PlaceHub(entity.Id);
            hub.SendToGroup(entity.Id.ToString(), message);
        }

        partial void Movements_Inserted(Movement entity)
        {
            string message = string.Format("A movement with id:{0}, car:{1}, address:{2}, till:{3} was just created by {4}"
                , entity.Id.ToString()
                , (entity.Car != null ? entity.Car.PlateNo : "(no car)")
                , (entity.Place != null && !string.IsNullOrEmpty(entity.Place.Address) ? entity.Place.Address : "(no address)")
                , (entity.DateTo != null ? entity.DateTo.Value.ToString("hh:mm") : "(no time)")
                , Application.User.Name);
            //var context = GlobalHost.ConnectionManager.GetHubContext<MovementHub>();
            //context.Clients.All.broadcastMessage(message);
        }

        partial void Movements_Updated(Movement entity)
        {
            string message = string.Format("A movement with id:{0}, car:{1}, address:{2}, till:{3} was just created by {4}"
                , entity.Id.ToString()
                , (entity.Car != null ? entity.Car.PlateNo : "(no car)")
                , (entity.Place != null && !string.IsNullOrEmpty(entity.Place.Address) ? entity.Place.Address : "(no address)")
                , (entity.DateTo != null ? entity.DateTo.Value.ToString("hh:mm") : "(no time)")
                , Application.User.Name);
            //var context = GlobalHost.ConnectionManager.GetHubContext<MovementHub>();
            //context.Clients.All.broadcastMessage(message);
        }

        partial void SaveChanges_ExecuteFailed(Exception exception)
        {
            ConcurrencyException e = exception as ConcurrencyException;
            if (e != null)
            {
                foreach (IEntityObject entityConflict in e.EntitiesWithConflicts)
                {
                    foreach (EntityPropertyConflict statusProperty in entityConflict.Details.EntityConflict.ConflictingProperties)
                    {
                        statusProperty.EntityConflict.ResolveConflicts(ConflictResolution.ClientWins);
                    }
                }
                //Resave once we’ve resolved the conflicts
                this.DataWorkspace.MMC_Content.SaveChanges();
            }
        }

        partial void SaveChanges_Executed()
        {

        }

        partial void SaveChanges_Executing()
        {

        }

        //partial void CrossCars_Filter(ref Expression<Func<CrossCar, bool>> filter)
        //{
        //    // If you are not an Administrator -- you can see all cars but yours
        //    if (!this.Application.User.HasPermission(Permissions.SecurityAdministration))
        //    {
        //        string userName = this.Application.User.Identity.Name;
        //        aspnet_User currentUser = this.DataWorkspace.MMC_Content.aspnet_Users1.Where(e => e.UserName == userName).FirstOrDefault();
        //        if (currentUser != null)
        //        {
        //            filter = e => e.Owner.UserName != userName;
        //        }
        //    }
        //}

    }
}
